package domain.dao.impl;

import java.sql.SQLException;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.HibernateTemplate;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

import domain.dao.interfaces.IDAOContact;
import domain.dao.interfaces.IDAOContactGroup;
import domain.dao.interfaces.IDAOPhoneNumber;
import domain.entities.impl.Contact;
import domain.entities.impl.PhoneNumber;
import domain.entities.interfaces.IAddress;
import domain.entities.interfaces.IContact;
import domain.entities.interfaces.IContactGroup;
import domain.entities.interfaces.IEntreprise;
import domain.entities.interfaces.IPhoneNumber;

public class DAOContact extends HibernateDaoSupport implements IDAOContact {

	// private final static String RESOURCE_JDBC = "java:comp/env/jdbc/dsMyDB";

	private HibernateTemplate hibernateTemplate;



	public void init() {
		setHibernateTemplate(getSessionFactory());
	}

	public void setHibernateTemplate(SessionFactory sessionFactory){
		this.hibernateTemplate= new HibernateTemplate(sessionFactory);
	}

	/* (non-Javadoc)
	 * @see domain.dao.impl.IDAOContact#addContact(org.hibernate.Session, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String[])
	 */
	public int addContact(
			final String firstName, final String lastName,
			final String email, final String street, final String city, 
			final String zip, final String country,
			final String mobile, final String house, final String work, String[] contactgroups) 
					throws Exception {


		ApplicationContext context = util.SpringUtils.getApplicationContext();
		IDAOPhoneNumber daoPhoneNumber = (IDAOPhoneNumber) context.getBean("beanDAOPhoneNumber");
		IDAOContact daoContact = (IDAOContact) context.getBean("beanDAOContact");
		IDAOContactGroup daoContactGroup = (IDAOContactGroup) context.getBean("beanDAOContactGroup");

		IContact contact = (IContact) context.getBean("beanContact");
		IAddress address = (IAddress) context.getBean("beanAddress");

		int idPhoneMobile = -1;
		int idPhoneHouse = -1;
		int idPhoneWork = -1;
		int idContact = -1;



		contact.setFirstName(firstName);
		contact.setLastName(lastName);
		contact.setEmail(email);
		contact.setAdd(address);
		contact.setChildsVersion(0);

		address.setCity(city);
		address.setCountry(country);
		address.setStreet(street);
		address.setZip(zip);


		hibernateTemplate.save(contact);


		idContact = contact.getId();

		idPhoneMobile = daoPhoneNumber.addPhoneNumber(
				"Mobile", mobile, idContact);
		idPhoneHouse = daoPhoneNumber.addPhoneNumber(
				"House", house, idContact);
		idPhoneWork = daoPhoneNumber.addPhoneNumber(
				"Work", work, idContact);

		addPhoneNumberToContact(idContact, idPhoneMobile);
		addPhoneNumberToContact(idContact, idPhoneHouse);
		addPhoneNumberToContact(idContact, idPhoneWork);



		if (contactgroups != null) {
			for (String contactgroup : contactgroups) {
				daoContactGroup.addContactToGroup(
						Integer.parseInt(contactgroup), idContact);
			}
		}


		return contact.getId();
	}

	/* (non-Javadoc)
	 * @see domain.dao.impl.IDAOContact#addEntreprise(org.hibernate.Session, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, int, java.lang.String[])
	 */
	public int addEntreprise(
			final String firstName, final String lastName,
			final String email, final String street, final String city, 
			final String zip, final String country,
			final String mobile, final String house, final String work, int siret, String[] contactgroups) 
					throws Exception {

		ApplicationContext context = util.SpringUtils.getApplicationContext();
		IDAOPhoneNumber daoPhoneNumber = (IDAOPhoneNumber) context.getBean("beanDAOPhoneNumber");
		IDAOContactGroup daoContactGroup = (IDAOContactGroup) context.getBean("beanDAOContactGroup");
		IEntreprise contact = (IEntreprise) context.getBean("beanEntreprise");
		IAddress address = (IAddress) context.getBean("beanAddress");

		int idPhoneMobile = -1;
		int idPhoneHouse = -1;
		int idPhoneWork = -1;
		int idContact = -1;



		contact.setFirstName(firstName);
		contact.setLastName(lastName);
		contact.setEmail(email);
		contact.setAdd(address);
		contact.setNumSiret(siret);
		contact.setChildsVersion(0);

		address.setCity(city);
		address.setCountry(country);
		address.setStreet(street);
		address.setZip(zip);


		hibernateTemplate.save(contact);


		idContact = contact.getId();

		idPhoneMobile = daoPhoneNumber.addPhoneNumber(
				"Mobile", mobile, idContact);
		idPhoneHouse = daoPhoneNumber.addPhoneNumber(
				"House", house, idContact);
		idPhoneWork = daoPhoneNumber.addPhoneNumber(
				"Work", work, idContact);

		addPhoneNumberToContact(idContact, idPhoneMobile);
		addPhoneNumberToContact(idContact, idPhoneHouse);
		addPhoneNumberToContact(idContact, idPhoneWork);



		if (contactgroups != null) {
			for (String contactgroup : contactgroups) {
				daoContactGroup.addContactToGroup(
						Integer.parseInt(contactgroup), idContact);
			}
		}


		return contact.getId();
	}

	/* (non-Javadoc)
	 * @see domain.dao.impl.IDAOContact#addPhoneNumberToContact(org.hibernate.Session, int, int)
	 */
	public void addPhoneNumberToContact(
			int idContact, int idPhone) throws Exception {


		IPhoneNumber phoneNumber = (IPhoneNumber) hibernateTemplate.get(
				PhoneNumber.class, idPhone);
		IContact contact = 
				(IContact) hibernateTemplate.get(Contact.class, idContact);


		phoneNumber.setContacts(contact);
		contact.getPhones().add(phoneNumber);


		hibernateTemplate.merge(phoneNumber);
		hibernateTemplate.merge(contact);
	}

	/* (non-Javadoc)
	 * @see domain.dao.impl.IDAOContact#deleteContact(org.hibernate.Session, int)
	 */
	public void deleteContact(int id) throws Exception {

		ApplicationContext context = util.SpringUtils.getApplicationContext();
		IContact contact = (IContact) hibernateTemplate.get(Contact.class, id);			
		IDAOContactGroup daoCG = (IDAOContactGroup) context.getBean("beanDAOContactGroup");
		IDAOPhoneNumber daoPhoneNumber = (IDAOPhoneNumber) context.getBean("beanDAOPhoneNumber");
		Set<IPhoneNumber> phones = new HashSet<IPhoneNumber>(contact.getPhones());
		Set<IContactGroup> books = new HashSet<IContactGroup>(contact.getBooks());


		
		for(IPhoneNumber p : phones) {
			daoPhoneNumber.deletePhoneNumber(p.getId());
 		}
		
		for(IContactGroup cg : books) {
			daoCG.removeContactFromGroup(cg.getGroupId(), contact.getId());
		}
		

		hibernateTemplate.delete(contact);
	}

	/* (non-Javadoc)
	 * @see domain.dao.impl.IDAOContact#updateContact(int, int, org.hibernate.Session, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String)
	 */
	public void updateContact(
			IContact contact,
			final String firstName, final String lastName,
			final String email, final String street, final String city, 
			final String zip, final String country,
			final String mobile, final String house, final String work) 
					throws Exception {


		ApplicationContext context = util.SpringUtils.getApplicationContext();
		IDAOPhoneNumber daoPhoneNumber = (IDAOPhoneNumber) context.getBean("beanDAOPhoneNumber");

		IAddress add = contact.getAdd();
		int idContact = contact.getId();



		add.setCity(city);
		add.setCountry(country);
		add.setStreet(street);
		add.setZip(zip);
		add.setCountry(country); 

		contact.setFirstName(firstName);
		contact.setLastName(lastName);
		contact.setEmail(email);



		hibernateTemplate.merge(contact);



	
		for (IPhoneNumber p : daoPhoneNumber.getByContactId(
				idContact)) {

			if (p.getPhoneKind().compareTo("Mobile") == 0) {
				daoPhoneNumber.updatePhoneNumber(
						p, p.getId(), "Mobile", mobile);
			} else if (p.getPhoneKind().compareTo("House") == 0) {
				daoPhoneNumber.updatePhoneNumber(
						p, p.getId(), "House", house);
			} else if (p.getPhoneKind().compareTo("Work") == 0) {
				daoPhoneNumber.updatePhoneNumber(
						p, p.getId(), "Work", work);
			}
		}	
	}

	/* (non-Javadoc)
	 * @see domain.dao.impl.IDAOContact#updateEnterprise(int, int, org.hibernate.Session, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, int)
	 */
	public void updateEnterprise(
			IEntreprise contact,
			final String firstName, final String lastName,
			final String email, final String street, final String city, 
			final String zip, final String country,
			final String mobile, final String house, final String work, int siret) 
					throws Exception {
		ApplicationContext context = util.SpringUtils.getApplicationContext();
		IDAOPhoneNumber daoPhoneNumber = (IDAOPhoneNumber) context.getBean("beanDAOPhoneNumber");

		IAddress add = contact.getAdd();
		int idContact = contact.getId();



		add.setCity(city);
		add.setCountry(country);
		add.setStreet(street);
		add.setZip(zip);
		add.setCountry(country); 

		contact.setFirstName(firstName);
		contact.setLastName(lastName);
		contact.setEmail(email);
		contact.setNumSiret(siret);



		hibernateTemplate.merge(contact);




		for (IPhoneNumber p : daoPhoneNumber.getByContactId(
				idContact)) {

			if (p.getPhoneKind().compareTo("Mobile") == 0) {
				daoPhoneNumber.updatePhoneNumber(
						p, p.getId(), "Mobile", mobile);
			} else if (p.getPhoneKind().compareTo("House") == 0) {
				daoPhoneNumber.updatePhoneNumber(
						p, p.getId(), "House", house);
			} else if (p.getPhoneKind().compareTo("Work") == 0) {
				daoPhoneNumber.updatePhoneNumber(
						p, p.getId(), "Work", work);
			}
		}	
	}


	/* (non-Javadoc)
	 * @see domain.dao.impl.IDAOContact#searchContact(java.lang.String[])
	 */
	public List<IContact> searchContact(final String[] patterns){

		return (List<IContact>) hibernateTemplate
				.execute(new HibernateCallback<List<IContact>>() {

					public List<IContact> doInHibernate(Session session)
							throws HibernateException, SQLException {


						//Business code
						StringBuffer strQuery = new StringBuffer(
								"select c from Contact c where (1 = 1) ");
						Query query = null;

						for(int i = 0 ; i < patterns.length ; i++) {
							strQuery.append("and (");
							strQuery.append("         (c.firstName LIKE '%"+patterns[i]+"%')");
							strQuery.append("      or (c.lastName LIKE '%"+patterns[i]+"%')");
							strQuery.append("      or (c.email LIKE '%"+patterns[i]+"%')");
							strQuery.append("      or (c.add.street LIKE '%"+patterns[i]+"%')");
							strQuery.append("      or (c.add.city LIKE '%"+patterns[i]+"%')");
							strQuery.append("      or (c.add.zip LIKE '%"+patterns[i]+"%')");
							strQuery.append("      or (c.add.country LIKE '%"+patterns[i]+"%')");
							strQuery.append("    ) ");
						}

						query = session.createQuery(strQuery.toString());
						return query.list();
					}
				});
	}

	/* (non-Javadoc)
	 * @see domain.dao.impl.IDAOContact#getAll()
	 */
	public List<IContact> getAll(){

		return (List<IContact>) hibernateTemplate
				.execute(new HibernateCallback<List<IContact>>() {

					public List<IContact> doInHibernate(Session session)
							throws HibernateException, SQLException {

						Query query = session.createQuery(
								"FROM Contact c");
						return query.list();
					}
				});
	}

	/* (non-Javadoc)
	 * @see domain.dao.impl.IDAOContact#getById(int)
	 */
	public IContact getById(final int id) {

		return (IContact) hibernateTemplate
				.execute(new HibernateCallback<IContact>() {

					public IContact doInHibernate(Session session)
							throws HibernateException, SQLException {


						//Business code
						Query query = session.createQuery(
								"FROM Contact c WHERE c.id = :id" 
								);
						query.setParameter("id", id);
						List result = query.list();

						return result.size() > 0 ? 
								(IContact) query.list().get(0) : 
									null;
					}
				});
	}
}